#include <fstream>
using namespace std;

#include "dyntype.h"
#include "dynobject.h"
#include <string.h>

struct __attribute__ ((__packed__)) EarningEstimate
{
  int analyst_id;
  char forecast_period_end_date[6];
  char periodicity[1];
  double estimate[2];

  static void register_dyntype() {
    CompoundDynType* dt = new CompoundDynType("EarningEstimate");
    dt->add_member("analyst_id", "int", offset(&EarningEstimate::analyst_id), 1);
    dt->add_member("forecast_period_end_date", "char[6]", offset(&EarningEstimate::forecast_period_end_date), 1);
    dt->add_member("periodicity", "char[1]", offset(&EarningEstimate::periodicity), 1);
    dt->add_member("estimate", "double", offset(&EarningEstimate::estimate), 2);
    DynTypeManager::get()->register_dyntype(dt);
  }
};
template <> inline DynType* get_dyntype<EarningEstimate>() { 
  return DynTypeManager::get()->get_dyntype("EarningEstimate");
}

void test1()
{
  DynType* dt = DynTypeManager::get()->get_dyntype("EarningEstimate");
  dt->print(cerr);
  cerr << "+++++++++++++++++++++++++++++++" << endl;
  
  EarningEstimate ee;
  DynObject dyno; 
  dyno.set_o_buf(DT("EarningEstimate"));
  dyno.print(cerr);
  cerr << "--------------------------------" << endl;    
  
  ee.analyst_id = 123;
  strncpy(ee.forecast_period_end_date, "200812", 
	  sizeof ee.forecast_period_end_date);
  ee.periodicity[0] = 'A';
  ee.estimate[1] = 123.456;
  ee.estimate[0] = -123.456;
  dyno.set_value<EarningEstimate>(ee);
  dyno.print(cerr);
  
  cerr << "=====================================" << endl;
  DynType* double_dt = DynTypeManager::get()->get_dyntype("double");
  double_dt->print(cerr);
  cerr << "+++++++++++++++++++++++++" << endl;
  
  DynObject ddyno(3456.0);
  ddyno.print(cerr);
  cerr << endl;

  cerr << "+++======================================" << endl;
}

void test2()
{
  ofstream out("testtypes.txt");
  {
    DynTypeManager::get()->save_dyntype(out, "EarningEstimate");
    cout << "saved:" << endl;
  }
  {
    DynTypeManager::get()->save_dyntype(out, "double");
    cout << "saved:" << endl;
  }
}

void test3()
{
  int i = 3;
  DynObject o(DT("int"));
  o.set_o_buf(membuf_t((char*)&i, sizeof(i)));
  o.print(cerr);
  i = 33;
  o.print(cerr); // still prints 3, data are copied into dynobject

  EarningEstimate ee;
  DynObject oo(DT("EarningEstimate"));
  oo.set_o_buf(membuf_t((char*)&ee, sizeof ee));
  oo.set_member<int>(22, "analyst_id");
  oo.print(cerr);
  int ii = oo.get_member<int>("analyst_id");
  cerr << ii << endl;
}

void test4()
{
  ifstream in("testtypes.txt");
  {
    string dyntypename;
    DynTypeManager::get()->clear();
    dyntypename = DynTypeManager::get()->load_and_register_dyntype(in);

    DynType* dt = DynTypeManager::get()->get_dyntype(dyntypename);
    dt->print(cout);
  }

  {
    string dyntypename;
    DynTypeManager::get()->clear();
    dyntypename = DynTypeManager::get()->load_and_register_dyntype(in);

    DynType* dt = DynTypeManager::get()->get_dyntype(dyntypename);
    dt->print(cout);
  }  
}

int main()
{
  try{
    EarningEstimate::register_dyntype();
    test1();
    test2();
    test3();
    test4();
  } catch (Error& e) {
    cerr << "error caught: " << e.msg() << endl;
  }
  return 0;
}
